#ifndef VARIABLEWIDTHFONT_H
#define VARIABLEWIDTHFONT_H

#include "font.h"

namespace Library
{

class PLIBEXP VariableWidthFont : public Library::Font
{
	public:
		struct ABC;
		struct Metric;
		struct Resource;
		struct ResourceShare;

	public:
				VariableWidthFont(const uint16* name);
				~VariableWidthFont();

		int32	ascent();
		
		String	bitmapName();

		int32	charOffset(const uint16 ch);

		uint32	codepageEntries();
		uint32	codepageOffset();

		int32	descent();

		void	drawText(int32 * x, int32 y, const uint16 ch, pCFrame frame);
		void	drawText(int32 * x, int32 y, const uint16* text, uint32 len, pCFrame frame);

		void	drawText(int32 * x, int32 y, const uint16 ch, pCBitmap bitmap);
		void	drawText(int32 * x, int32 y, const uint16* text, uint32 len, pCBitmap bitmap);

		int32	externalLeading();

		void	glyphMetric(int32 * width, int32 * height, int32 * left,
			int32 * right, int32 * top, int32 * bottom, const uint16 ch);
		void	glyphMetric(int32 * width, int32 * height, int32 * left,
					int32 * right, int32 * top, int32 * bottom, const uint16* text, uint32 len);

		bool8	isA(uint32 type);

		uint32	kind();

		int32	maximumGlyphHeight();
		int32	maximumGlyphWidth();

		int32	maximumTextHeight();
		int32	maximumTextWidth();

		void	textMetric(int32 * width, int32 * height, int32 * abcA,
			int32 * abcC, const uint16 ch);
		void	textMetric(int32 * width, int32 * height, int32 * abcA,
					int32 * abcC, const uint16* text, uint32 len);

        const String& getName() const { return mName; }

	protected:
		Resource *			mResource;
		pCBitmap				mBitmap;
		Metric *			mMetrics;
		uint32				mMaxGlyphHeight;
		uint32				mMaxGlyphWidth;
        String              mName;

		// Every VariableWidthFont of the same resource shares the same pointer.
		ResourceShare *		mResourceShare;

	// prohibited
	private:
		VariableWidthFont(VariableWidthFont &);
		VariableWidthFont & operator=(VariableWidthFont &);
};

//----------------------------------------------------------------------------
// Structs, public
//
#pragma pack(push, 1)
struct VariableWidthFont::ABC
{
	int32	a;
	int32	b;
	int32	c;
	int32	_d;		// padding
};

struct VariableWidthFont::Metric
{
	uint32	x;
	uint32	y;
	uint32	width;
	uint32	height;
	int32	dx;
	int32	dy;
	ABC		abc;
};

struct VariableWidthFont::Resource
{
	Font::Resource	super;
	uint32			flags;
	int32			ascent;
	int32			descent;
	int32			externalLeading;
	int32			maxCharWidth;
	uint32			nameLength;
	uint32			nameOffset;
	uint32			codepageEntries;
	uint32			codepageOffset;
};

struct VariableWidthFont::ResourceShare
{
	Resource *		resource;
	pCBitmap			bitmap;
	Metric *		metrics;
	uint32			maxGlyphHeight;
	uint32			maxGlyphWidth;
};
#pragma pack(pop)

//----------------------------------------------------------------------------
// Inline, public
//
#define FLAG_TOGGLE(variable, flag, conditional)							\
		do {																\
			if (conditional)												\
				variable |= (flag);											\
			else															\
				variable &= ~(flag);										\
		} while (0);

#define FLAG_CHECK(variable, flag)											\
		((variable & (flag)) != 0)

inline int32
VariableWidthFont::ascent()
{
	return mResource->ascent;
}

inline uint32
VariableWidthFont::codepageEntries()
{
	return mResource->codepageEntries;
}

inline uint32
VariableWidthFont::codepageOffset()
{
	return mResource->codepageOffset;
}

inline int32
VariableWidthFont::descent()
{
	return mResource->descent;
}

inline int32
VariableWidthFont::externalLeading()
{
	return mResource->externalLeading;
}

inline int32
VariableWidthFont::maximumGlyphHeight()
{
	return mMaxGlyphHeight;
}

inline int32
VariableWidthFont::maximumGlyphWidth()
{
	return mMaxGlyphWidth;
}

inline int32
VariableWidthFont::maximumTextHeight()
{
	return mResource->ascent + mResource->descent;
}

inline int32
VariableWidthFont::maximumTextWidth()
{
	return mResource->maxCharWidth;
}

inline String
VariableWidthFont::bitmapName()
{
	char* name = (char*)mResource;

	return name + mResource->nameOffset;
}

}; // namespace Library

#endif
